package com.qf.aspect;

import com.qf.util.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

/**
 * 日志切面类
 *
 * @USER: Administrator
 * @DATE: 2025/9/2 下午8:01
 * @VERSION: 1.0.0
 */
@Aspect
@Component
@EnableAspectJAutoProxy
public class LogAspect {

    /**
     * 切入点表达式
     */
    @Pointcut("execution(* com.qf.service.impl.*.*(..))")
    public void Pointcut() {}

    /**
     * 前置通知：在目标方法执行前执行
     * @param joinPoint 切点对象，包含连接点信息
      */
    @Before("Pointcut()")
    public void beforeAdvice(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("前置通知：方法 " + methodName + " 即将执行");
    }

    /**
     * 后置通知：在目标方法执行后执行（无论是否异常）
     * @param joinPoint 切点对象，包含连接点信息
     */
    //
    @After("Pointcut()")
    public void afterAdvice(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("后置通知：方法 " + methodName + " 执行完毕");
    }

    /**
     * 返回通知：在目标方法正常返回后执行
     * @param joinPoint 切点对象，包含连接点信息
      */
    @AfterReturning(pointcut = "Pointcut()", returning = "result")
    public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("返回通知：方法 " + methodName + " 返回结果：" + result);
    }

    /**
     * 异常通知：在目标方法抛出异常时执行
      */
    @AfterThrowing(pointcut = "Pointcut()", throwing = "ex")
    public void afterThrowingAdvice(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("异常通知：方法 " + methodName + " 抛出异常：" + ex.getMessage());
    }

    /**
     * 环绕通知：包围目标方法执行，可以控制方法执行
     */
    @Around("Pointcut()")
    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        String methodName = proceedingJoinPoint.getSignature().getName();
        long startTime = System.currentTimeMillis();

        // 执行目标方法
        Object result = proceedingJoinPoint.proceed();

        // 获取当前登录用户信息
        System.out.println(SecurityUtils.getCurrentUser());

        long endTime = System.currentTimeMillis();
        System.out.println("环绕通知：方法 " + methodName + " 执行时间：" + (endTime - startTime) + "ms");

        return result;
    }

}
